package com.george.payment.wechat.config;

import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.impl.client.CloseableHttpClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import javax.annotation.Resource;
import java.io.FileInputStream;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.Signature;
import java.util.Base64;

/**
 * @title: WxPayConfig.java
 * @description: 微信支付配置类
 * @author: George
 * @date: 2023/6/27 16:28
 */
@Configuration
@Slf4j
public class WxPayConfig {

    @Resource
    private WeixinPayProperties weixinPayProperties;

    /**
     * 获取支付签名
     *
     * @param signStr
     * @return java.lang.String
     * @author George
     * @date 2023/6/28 16:31
     */
    public String paySign(String signStr) {
        String paySign = "";
        try {
            // 签名
            Signature sign = Signature.getInstance("SHA256withRSA");
            // 获取商户私钥并进行签名
            PrivateKey privateKey = getPrivateKey();
            sign.initSign(privateKey);
            sign.update(signStr.getBytes(StandardCharsets.UTF_8));
            paySign = Base64.getEncoder().encodeToString(sign.sign());
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取支付签名失败，待签名内容：{}，异常信息：{}", signStr,e.getMessage());
            return null;
        }
        return paySign;
    }

    /**
     * 获取商户的私钥文件
     *
     * @param
     * @return java.security.PrivateKey
     * @author George
     * @date 2023/6/27 16:31
     */
    private PrivateKey getPrivateKey() {
        try {
            //将相对路径转换为绝对路径
            String privateKeyPath = weixinPayProperties.getPrivateKeyPath();
            if (privateKeyPath.startsWith("classpath:")) {
                privateKeyPath = privateKeyPath.replace("classpath:", "");
                ClassPathResource resource = new ClassPathResource(privateKeyPath);
                String absolutePath = resource.getFile().getAbsolutePath();
                weixinPayProperties.setPrivateKeyPath(absolutePath);
            }
            return PemUtil.loadPrivateKey(new FileInputStream(weixinPayProperties.getPrivateKeyPath()));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("微信支付私钥文件加载失败");
//            throw new BaseException("微信支付私钥文件加载失败", e);
            return null;
        }
    }

    /**
     * 获取微信支付签名验证器
     *
     * @param
     * @return com.wechat.pay.contrib.apache.httpclient.auth.Verifier
     * @author George
     * @date 2023/6/27 16:33
     */
    @Bean
    public Verifier getVerifier() {
        try {
            log.info(" 获取微信支付签名验证器");
            //获取商户私钥
            PrivateKey privateKey = getPrivateKey();
            // 私钥签名对象
            PrivateKeySigner keySigner = new PrivateKeySigner(weixinPayProperties.getMerchantSerialNumber(), privateKey);
            // 身份认证对象
            WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(weixinPayProperties.getMerchantId(), keySigner);
            // 获取证书管理器实例，会定时下载和更新商户的微信平台证书（默认下载间隔为UPDATE_INTERVAL_MINUTE）
            CertificatesManager certificatesManager = CertificatesManager.getInstance();
            // 向证书管理器增加需要自动更新平台证书的商户信息
            certificatesManager.putMerchant(weixinPayProperties.getMerchantId(), wechatPay2Credentials,
                    weixinPayProperties.getApiV3key().getBytes(StandardCharsets.UTF_8));
            // 若有多个商户号，可继续调用putMerchant添加商户信息
            Verifier verifier = certificatesManager.getVerifier(weixinPayProperties.getMerchantId());
            return verifier;
        } catch (Exception ex) {
            ex.printStackTrace();
            log.error("获取微信支付签名验证器异常，异常信息：{}", ex.getMessage());
//            throw new BaseException("获取微信支付签名验证器异常");
            return null;
        }
    }

    /**
     * 获取微信支付http请求客户端
     *
     * @return org.apache.http.impl.client.CloseableHttpClient
     * @author George
     * @date 2023/6/27 16:36
     */
    @Bean
    public CloseableHttpClient getWxPayHttpClient() {
        log.info("获取微信支付http请求客户端");
        //获取商户私钥
        PrivateKey privateKey = getPrivateKey();
        // 从证书管理器中获取verifier
        Verifier verifier = getVerifier();
        WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
                .withMerchant(weixinPayProperties.getMerchantId(), weixinPayProperties.getMerchantSerialNumber(), privateKey)
                .withValidator(new WechatPay2Validator(verifier));
        // ... 接下来，你仍然可以通过builder设置各种参数，来配置你的HttpClient
        // 通过 WechatPayHttpClientBuilder 构造的 HttpClient，会自动的处理签名和验签，并进行证书自动更新
        CloseableHttpClient httpClient = builder.build();
        return httpClient;
    }
}

